﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mogre;

namespace WastedMechanics.CharState
{
    public abstract class CharStateClimb : CharState
    {
        public enum ClimbStates
        {
            Pushing,
            Jumping,
            Climbing
        }

        ClimbStates ClimbState;
        public string PushAnimationName;
        public string JumpAnimationName;
        public string ClimbAnimationName;

        public CharStateClimb(Character chr, string pushAnimName, string jumpAnimName, string climbAnimName)
            : base(chr)
        {
            PushAnimationName = pushAnimName;
            JumpAnimationName = jumpAnimName;
            ClimbAnimationName = climbAnimName;
        }

        public override void Enter()
        {
            Character.ResetAnimation(PushAnimationName);
            Character.SetAnimation(PushAnimationName);
            Character.CanTurn = false;
            ClimbState = ClimbStates.Pushing;
        }

        public override void Exit()
        {
            Character.IsJumping = false;
        }

        public override void Update()
        {
            switch (ClimbState)
            {
                case ClimbStates.Pushing:
                    if (Character.AnimBlender.Target.TimePosition > Character.AnimBlender.Target.Length * 0.99f)
                    {
                        float impulsePower = Mogre.Math.Sqrt((Character.ClimbOrigin.y - Character.Position.y) * 100);
                        if (Character.ClimbOrigin.y - Character.Position.y <= 0 || impulsePower < 4f)
                            impulsePower = 4f;
                        
                        if (impulsePower > 0)
                        {
                            Character.Body.AddImpulse(new Vector3(
                                0,
                                impulsePower,
                                0), Character.Position);
                            ClimbState = ClimbStates.Jumping;
                            Character.IsJumping = true;
                            Character.SetAnimation(JumpAnimationName);
                        }
                        else
                            Character.SwitchState(GetIdleState());
                    }
                    break;
                case ClimbStates.Jumping:
                    if (Character.Position.y >= Character.ClimbOrigin.y)
                    {
                        Character.Body.SetMassMatrix(0, Vector3.ZERO);                                
                        ClimbState = ClimbStates.Climbing;
                        Character.ResetAnimation(ClimbAnimationName);
                        Character.SetAnimation(ClimbAnimationName);                                           
                    }
                    if (Character.Body.Velocity.y < 0)
                        Character.SwitchState(GetIdleState());
                    break;
                case ClimbStates.Climbing:
                    Character.Body.SetPositionOrientation(
                        Character.ClimbOrigin + Character.Orientation * Character.BodyEntity.Skeleton.GetBone("Spine1")._getDerivedPosition(), 
                        Character.Orientation
                        );
                    Character.Node.Position = Character.ClimbOrigin;
                    if (Character.AnimBlender.Target.TimePosition > Character.AnimBlender.Target.Length * 0.99f)
                    {
                        Character.Body.SetMassMatrix(Character.Profile.BodyMass, Character.Inertia);
                        Character.Body.AutoSleep = false;
                        Character.Node.Position = Character.Body.Position;
                        CharStateIdle idle = GetIdleState() as CharStateIdle;
                        Character.AnimBlender.SetAnimationInstantly(idle.AnimationName);
                        Character.SwitchState(idle);  
                    }
                    break;
            }
        }

        public abstract CharState GetIdleState();        
    }
}
